import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 0,
    age: 18,
    name: 'zs',
  },
  getters: {
    doubleCount(state) {
      // 计算属性的结果 怎么丢出去？通过返回值丢出去
      return state.count * 2
      // setTimeout(() => {
      // return state.count * 2
      // }, 5000)
    },
  },
  mutations: {
    // 用来定义 一个个的 mutation
    //  一个 mutation 说白了，就是一个函数
    //    第一个参数：当前的所有状态
    //    第二个参数：额外的载荷（数据）（注意：只能接受一个载荷数据，如果要传多个，请用数组或对象）
    addCount(state, payload) {
      // 在 mutation 函数中，如何修改 state 中的数据呢？
      // 可以通过第一个形参，接收到所有的 state

      // if (payload instanceof Array) {
      // }
      if (Array.isArray(payload)) {
        payload = payload.reduce((sum, v) => sum + v, 0)
      }

      state.count += payload
    },
  },
  actions: {
    addCount(ctx, payload) {
      // 延迟1秒
      setTimeout(() => {
        // 想要改数据，需要调 mutation
        // 如何在 action 中调用 mutation 呢？
        //  可以通过第一个形参，接收到当前上下文（当前所处环境）（当前所处模块环境）（根模块）
        ctx.commit('addCount', payload)
      }, 1000)
    },
  },
  modules: {
    // 键：模块名字
    // 值：模块配置
    user: {
      // 开启命名空间，默认不开启（false）
      // 一旦开启，该模块下的 getters/mutations/actions 就不会往根模块上挂载，和 state 一样，属于独立的
      // 建议1：无脑加（只要写了子模块，就加）
      // 建议2：写子模块时，先把这个加上
      namespaced: true,
      // 默认情况下，所有子模块的state会互相独立
      state: {
        // 用户列表
        list: ['张三', '李四'],
      },
      // 默认情况下，会将所有子模块的 getters 统统合并到根模块下
      getters: {
        listLength(state, getters, rootState, rootGetters) {
          console.log(this, '子模块下的getter中的this')
          return state.list.length
        },
      },
      // 默认情况下，mutations 也和 getters 一样，所有子模块也会合并到根模块下
      mutations: {
        addUser(state, payload) {
          console.log(this, '子模块下的mutation中的this')
          // 这个 this 指的是根模块的 store 实例，也就是 $store
          // this.state.子模块名称.子模块状态名称
          // this.getters['子模块名称/子模块getter名称']
          // this.commit('子模块名称/子模块的mutation名称')
          // this.dispatch('子模块名称/子模块的action名称')
          state.list.push(payload)
        },
      },
      // actions 也和 getters 一样
      actions: {
        // ctx ==> 当前模块的上下文，
        addUser(ctx, payload) {
          console.log(this, '子模块下的action中的this')
          // 这里的 this 也是 $store
          setTimeout(() => {
            ctx.commit('addUser', payload)
          }, 1000)
        },
      },
    },
    goods: {
      namespaced: true,
      state: {
        list: ['小米13', '华为meta50', 'iPhone15'],
      },
      // 默认情况下，会将所有子模块的 getters 统统合并到根模块下
      getters: {
        // state ==> 当前模块的状态
        // getters ==> 当前模块的getters
        // rootState ==> 根模块的状态
        // rootGetters ==> 根模块的getters
        listLength(state, getters, rootState, rootGetters) {
          // 如何在子模块中访问根模块的 state 和 getters ？
          // rootState.子模块名字.子模块的状态
          // rootGetters['子模块的名字/子模块的getter名字']
          return state.list.length
        },
      },
      mutations: {
        // state ==> 当前模块的state
        delLastGoods(state) {
          state.list.pop()
        },
      },
      actions: {
        // ctx ==> 当前模块的上下文
        delLastGoods(ctx) {
          return new Promise((resolve, reject) => {
            // promise 在创建出来时候，初始状态为 pending
            // 只要调用了 resolve 就表示，该 promise 的状态变成已完成 fulfilled
            // 只要调用了 reject 就表示，该 promise 的状态变成已完成 rejected
            // 如何在actions中访问其他模块的 state 和 getters

            // ctx.rootState
            // ctx.rootGetters

            setTimeout(() => {
              ctx.commit('delLastGoods')

              // 完成
              resolve()

              // 在删除最后一个商品后，让根模块下的 count -1
              //   commit 函数的前两个参数我们都知道，第三个参数表示额外的配置项，root: true，表示从根模块开始找
              // ctx.commit('addCount', -1)
              ctx.commit('addCount', -1, { root: true })

              // 如果还要调用 user 模块下的 addUser action呢？
              ctx.dispatch('user/addUser', '老六', { root: true })
            }, 1000)
          })
        },
      },
    },
  },
})
